from django.test import TestCase
from mixer.backend.django import mixer

from api.models import Run, Record, User
from api.views.algorithm.views import ALGORITHM
from scripts.monitor_thread import MonitorThread
from scripts.auto_docker import DockerAutomation

import random, json, time
from datetime import datetime, timedelta


def insert_test_data(record_nums, choices, wrong_info=""):
    run_nums = 0
    # 插入 30 条已完成的算法，并将其中的 [0, 1] 插入 Run 中
    for i in range(record_nums):
        # 随机选择一个算法 ID
        if wrong_info:
            algorithm_id = "5"
        else:
            algorithm_id = random.choice(list(ALGORITHM.keys()))
        algorithm_status = random.choice(choices)
        if algorithm_status == 2:
            d_result = f"这是算法 {algorithm_id} 的运行结果"
        else:
            d_result = ""

        record = mixer.blend(
            Record,
            status=algorithm_status,  # 假设状态是 0, 1, 2, 3
            params=json.dumps(
                {
                    "user_name": "aiops@admin",
                    "algorithm": {
                        "id": algorithm_id,
                        "name": ALGORITHM[algorithm_id]["name"],
                        "start_time": (
                            datetime.now() - timedelta(days=i + 1)
                        ).timestamp(),
                        "end_time": (datetime.now() - timedelta(days=i)).timestamp(),
                    },
                }
            ),
            create_time=datetime.now(),
            result=json.dumps({"result": d_result}),
        )

        if record.status in [0, 1]:
            run_nums += 1
            run = mixer.blend(
                Run,
                id=record.id,
                status=record.status,
                params=record.params,  # 假设状态是 0, 1
            )

    print(f"run 总数为: {run_nums}.")
    print(f"record 总数为: {record_nums}.")


class MonitorThreadTestCase(TestCase):
    def setUp(self):
        self.mtr = MonitorThread(3, 3)
        self.docker_automation = DockerAutomation()

    def test_onlyOneMonitor(self):
        mtr1 = MonitorThread(3, 3)
        mtr2 = MonitorThread(4, 4)
        self.assertEqual(mtr1, mtr2)
    
    def test_MonitorThread_init(self):
        # self.cur_docker_count < self.max_docker_count
        mtr1 = MonitorThread(3, 3)
        self.assertIsNotNone(mtr1)
        # self.cur_docker_count > self.max_docker_count:
        mtr2 = MonitorThread(3, 1)
        self.assertIsNotNone(mtr2)
    
    def test_MonitorThread_stop(self):
        try:
            self.mtr.stop()
        except Exception as e:
            self.fail(f'test_MonitorThread_stop raised an exception: {e}')
    
    def test_run_algorithms(self):
        insert_test_data(1, [0])
        run_instance = Run.objects.last()
        self.mtr.run_algorithms(run_instance, self.docker_automation)
        # 判断状态是否更新
        run_instance.refresh_from_db()
        self.assertEqual(run_instance.status, 1)
        # # 删除容器
        self.mtr.delete_algorithms(run_instance, self.docker_automation)
    
    def test_check_done(self):
        insert_test_data(1, [0])
        run_instance = Run.objects.last()
        self.mtr.run_algorithms(run_instance, self.docker_automation)
        # 检测是否完成
        try:
            self.mtr.check_done(run_instance, self.docker_automation)
        except Exception as e:
            self.fail(f'test_check_done raised an exception: {e}')
        # 删除容器
        self.mtr.delete_algorithms(run_instance, self.docker_automation)
    
    def test_delete_algorithms(self):
        # task.docker_id == ""
        insert_test_data(1, [0])
        run_instance = Run.objects.last()
        self.mtr.delete_algorithms(run_instance, self.docker_automation)
        self.assertEqual(list(Run.objects.filter(id=run_instance.id)), [])
        
        # task.docker_id != ""
        insert_test_data(1, [0])
        run_instance = Run.objects.last()
        self.mtr.run_algorithms(run_instance, self.docker_automation)
        container_id = run_instance.docker_id
        self.mtr.delete_algorithms(run_instance, self.docker_automation)
        self.assertEqual(list(Run.objects.filter(id=run_instance.id)), [])
        self.assertIsNone(self.docker_automation.get_container(container_id))